<template>
  <vxe-modal
    v-model="showModal"
    show-footer
    class-name="au-modal"
    :title="title"
    width="460px"
    v-bind="$attrs"
    @close="closePopup"
  >
    <div v-show="!showInput" class="message-box-body">
      <p :class="['icon', classType[option.type as Sign]]">
        <IconifyIconOnline icon="pepicons-pop:exclamation-circle-filled" />
      </p>
      <component :is="message" v-if="isFunction(message)" />
      <p v-else class="message">{{ message }}</p>
    </div>
    <div v-show="showInput" class="message-box-body px-[20px]">
      <div class="flex items-center">
        <div :style="{ width: message.length * 20 + 'px' }">{{ message }}</div>
        <ElInput
          ref="inputRef"
          v-model="state.inputValue"
          :placeholder="state.inputPlaceholder"
          :aria-invalid="state.validateError"
          :maxlength="100"
          :class="[
            state.validateError ? 'invalid' : '',
            'flex-grow overflow-hidden'
          ]"
          @keydown.enter="handleInputEnter"
        />
      </div>
      <div
        class="error-msg"
        :style="{
          visibility: !!state.editorErrorMessage ? 'visible' : 'hidden',
          paddingLeft: message.length * 20 - 12 + 'px'
        }"
      >
        {{ state.editorErrorMessage }}
      </div>
    </div>
    <template #footer>
      <div class="flex h-full">
        <div class="ml-auto h-full">
          <el-button v-if="showCancel" @click="handleAction('cancel')"
            >{{ $t("buttons.pureCancel") }}
          </el-button>
          <el-button type="primary" @click="handleAction('confirm')"
            >{{ $t("buttons.pureConfirm") }}
          </el-button>
        </div>
      </div>
    </template>
  </vxe-modal>
</template>

<script setup lang="ts">
import { nextTick, reactive, ref, watch } from "vue";
import { VxeModal } from "vxe-pc-ui";
import { ElButton, ElInput } from "element-plus";
import { IconifyIconOnline } from "@/components/ReIcon";
import { isFunction } from "@pureadmin/utils";
import { useI18n } from "vue-i18n";
import { Props, Sign, Action, TextType } from "./message-box.type";

const props = withDefaults(defineProps<Props>(), {
  message: "",
  showCancel: true
});

const emit = defineEmits(["action", "confirm"]);

const { t } = useI18n();
const showModal = ref(true);
const classType = ref({
  warning: "warning",
  error: "error"
});

const state = reactive({
  validateError: false,
  inputPlaceholder: "",
  inputPattern: null,
  inputValue: "",
  editorErrorMessage: "",
  inputErrorMessage: "",
  inputValidator: null,
  action: "" as Action,
  inputType: "text" as TextType
});

const validate = () => {
  if (props.boxType === "prompt") {
    const inputPattern = state.inputPattern;
    if (inputPattern && !inputPattern.test(state.inputValue || "")) {
      state.editorErrorMessage =
        state.inputErrorMessage || t("el.messagebox.error");
      state.validateError = true;
      return false;
    }
    const inputValidator = state.inputValidator;
    if (typeof inputValidator === "function") {
      const validateResult = inputValidator(state.inputValue);
      if (validateResult === false) {
        state.editorErrorMessage =
          state.inputErrorMessage || t("el.messagebox.error");
        state.validateError = true;
        return false;
      }
      if (typeof validateResult === "string") {
        state.editorErrorMessage = validateResult;
        state.validateError = true;
        return false;
      }
    }
  }
  state.editorErrorMessage = "";
  state.validateError = false;
  return true;
};

const handleInputEnter = (e: KeyboardEvent) => {
  if (state.inputType !== "textarea") {
    e.preventDefault();
    return handleAction("confirm");
  }
};

const handleAction = (action: Action) => {
  if (props.boxType === "prompt" && action === "confirm" && !validate()) {
    return;
  }

  state.action = action;

  closePopup();
};

const handleConfirm = () => {
  showModal.value = false;
  emit("confirm");
};

const closePopup = () => {
  if (!showModal.value) return;
  showModal.value = false;
  nextTick(() => {
    if (state.action) emit("action", state.action, state.inputValue);
  });
};

watch(
  () => state.inputValue,
  async val => {
    await nextTick();
    if (props.boxType === "prompt" && val !== null) {
      validate();
    }
  },
  { immediate: true }
);

watch(
  () => props,
  val => {
    if (val.boxType === "prompt") {
      state.inputValue = val.option.inputValue;
      state.inputPlaceholder = val.option.inputPlaceholder;
      state.inputPattern = val.option.inputPattern;
      state.inputType = val.option.inputType;
      state.inputErrorMessage = val.option.inputErrorMessage;
      state.inputValidator = val.option.inputValidator;
    }
  },
  {
    immediate: true
  }
);
</script>

<style lang="scss">
.au-modal {
  &.vxe-modal--wrapper.type--modal .vxe-modal--header {
    height: auto;
    border-bottom: 1px solid var(--autata-border-color);
  }

  .vxe-modal--footer {
    padding: 0.8em 1em;
    box-shadow: inset 0 1px 0 0 var(--autata-border-color);
  }

  .vxe-modal--header-title {
    padding: 20px;
    font-size: 14px;
    color: var(--autata-font-color);
  }

  .vxe-modal--header-right {
    .vxe-modal--close-btn,
    .vxe-modal--zoom-btn {
      color: var(--autata-font-gray-color);
    }
  }

  .el-button {
    padding: 9px 20px;
    border-radius: 2px;
  }

  .message-box-body {
    margin-top: 46px;
    margin-bottom: 46px;

    .message {
      text-align: center;
    }

    .invalid {
      .el-input__wrapper {
        box-shadow: 0 0 0 1px var(--el-color-danger, var(--el-border-color))
          inset;
      }
    }

    .error-msg {
      color: var(--el-color-danger);
    }

    .icon {
      margin-bottom: 20px;
      color: var(--autata-icon-color);
      text-align: center;

      &.warning {
        --autata-icon-color: #f5a61e;
      }

      &.error {
        --autata-icon-color: #ea2626;
      }

      svg {
        width: 66px;
        height: 66px;
        margin: 0 auto;
      }
    }
  }
}
</style>
